#include "Vector.h"
#include "Block Grid.h"

//VectorData
VectorData::~VectorData() {
	switch(this->GetDataType())									
	{															
	case VOIDP:			_DELETE(Data);
		break;						
	case INTEGERP :		_DELETE((int*)Data);
		break;			
	case FLOATP :		_DELETE((float*)Data);
		break;			
	case DOUBLEP :		_DELETE((double*)Data);
		break;			
	case CHARP :		_DELETE((char*)Data);
		break;				
	case BLOCK_GRID :	_DELETE((BlockGrid*)Data);
		break;	
	default :			Data = NULL; break;						
	}															
	Data_Type = EMPTY ;									
}

void VectorData::SetDatawType(void * D,int Type) {
	Data = D;
	SetDataType(Type);
}

void VectorData::SetDataType(int Type) {
	Data_Type = Data_Type | Type;
	Data_Type = Data_Type & Type;
}



//Vector
void Vector::Ensure_Capacity(int a_size)
{
	VectorData ** biggerArray = NULL;
	// if we have no array
	if(m_ptr == 0){
		//make an array
		m_allocated = 5;
		m_ptr = new VectorData*[m_allocated];
	}
	// if our array is not big enough
	if(a_size >= m_allocated){
		// make a bigger array
		biggerArray = new VectorData*[m_allocated+5];
		// copy the old values into the new array
		for(int i = 0; i < m_allocated; ++i)
		{
			biggerArray[i] = new VectorData( m_ptr[i] );
		}
		// delete the old array
		delete [] m_ptr;
		// make the ptr point at the new array
		m_ptr = biggerArray;
		m_allocated += 5;
	}
}

void Vector::Init()
{
	m_ptr = NULL;
	m_size = 0;
	m_allocated = 0;
	Ensure_Capacity(m_size);
}

void Vector::Clear() {
	for(int i = 0;i < m_size;i++)
		delete m_ptr[i];
	delete [] m_ptr;
	m_ptr = NULL;
	m_size = 0;
	m_allocated = 0;
}

void Vector::Set(int a_index, int a_DataType , void * a_value){
	m_ptr[a_index]->SetDatawType(a_value,a_DataType);
}

VectorData * Vector::Get(int const & a_index) const{
	return m_ptr[a_index];
}

const int Vector::Index_Of(void * a_value){
	for(int i = 0; i < m_size; i++)
	{
		if(m_ptr[i]->GetData() == a_value)
			return i;
	}
	return -1;
}

void Vector::Add(VectorData * V) {
	Add(V->GetDataType(),V->GetData());
}

void Vector::Add(VectorData V) {
	Add(V.GetDataType(),V.GetData());
}

void Vector::Add(int a_DataType,void * a_value){
	// make sure we have enough array to add to
	Ensure_Capacity(m_size);
	// add to the array
	m_ptr[m_size++] = new VectorData(a_DataType,a_value);
}

//void Vector::Sort()
//{
//	int j,i;
//	int key;
//	for(j = 1; j < m_size; ++j)
//	{
//		key = m_ptr[j].GetDataType();
//		i = j - 1;
//		while(i >= 0 && m_ptr[i].GetDataType() > key)
//		{
//			m_ptr[i+1] = m_ptr[i];
//			i--;
//		}
//		m_ptr[i+1].GetDataType = key;
//	}
//}

bool Vector::Empty(){
	if(m_size<=0)
		return true;
	else return false;
}

void Vector::Insert(int a_index, void * a_value,int a_DataType){
	// what if there is not enough to insert?
	Ensure_Capacity(m_size+1);
	// shift all of the elements over
	for(int i = m_size; i > a_index; --i)
	{
		m_ptr[i] = m_ptr[i-1];
	}
	// put the new element in its spot
	m_ptr[a_index] = new VectorData(a_DataType,a_value);
	m_size++;
}

bool Vector::Has(void * a_value) {
	for(int i = 0; i < m_size; ++i)
	{
		if(a_value == m_ptr[i]->GetData())
		{
			return true;
		}
	}
	return false;
}

void Vector::Remove_by_Value(VectorData V) {
	Remove_by_Value(V.GetData());
}

void Vector::Remove_by_Value(VectorData * V) {
	Remove_by_Value( V->GetData() );
}

void Vector::Remove_by_Value(void * a_value){
	int j = -1;
	bool Found = false;
	VectorData * hold;
	for(int i = 0; i < m_size; ++i)
	{
		if(a_value == m_ptr[i]->GetData())
		{
			if(!Found)
			{
				Found = true;
				j = i;
				hold = m_ptr[i];
			}
		}
	}
	if(Found)
	{
		m_size--;
		int i;
		for(i = j; i < m_size; ++i)
		{
			m_ptr[i] = m_ptr[i+1];
		}
		m_ptr[i] = NULL;
	}
	delete hold;
}

void Vector::Add_Vector(Vector * V){
	for(int i = 0;i < V->m_size;++i)
	{
		Add(V->Get(i)->GetDataType(),V->Get(i)->GetData());
	}
}